home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / vn / part01 next >
Encoding:
Internet Message Format  |  1987-02-16  |  60.6 KB

  1. Subject:  v08i064:  The VN news reader, Part01/03
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: rtech!bobm (Bob Mcqueer)
  6. Mod.sources: Volume 8, Issue 64
  7. Archive-name: vn/Part01
  8.  
  9. This is the source for the alternate news reader vn.  I'm sending
  10. you the four archives I put up in net.sources as four separate
  11. mail messages.  Archive 1 contains documentation and a README file
  12. concerning installation.  I tried to make these archives about the
  13. size that seemed to be acceptable in existing mod.sources postings -
  14. about 40K each.  If you are a devoted user of the other readers, copy
  15. your .newsrc before you give this one a try - you might not like what
  16. it does.  My justification is that a pretty fair number of people DO
  17. like what it does - consider it an alternate paradigm which basically
  18. got its start a few years back because I was getting sick of beating
  19. on the 'n' key.
  20.  
  21. Bob McQueer
  22. {amdahl, sun, mtxinu, hoptoad, cpsc6a}!rtech!bobm
  23.  
  24. [  We use notes internally -- I haven't tried this.  --r$  ]
  25. #! /bin/sh
  26. # This is a shell archive.  Remove anything before this line,
  27. # then unpack it by saving it in a file and typing "sh file".
  28. # If all goes well, you will see the message "End of archive 1 (of 3)."
  29. # Contents:  MANIFEST README config.h digest.c envir_set.c groupdir.c
  30. #   hash.c head.h mf.nore mf.re mf.sysv newsrc.c pagefile.c reader.h
  31. #   reg.c sig_set.c storage.c strings.c tmpnam.c
  32. # Wrapped by rs@mirror on Tue Feb 17 12:10:01 1987
  33. PATH=/bin:/usr/bin:/usr/ucb; export PATH
  34. echo shar: extracting "'MANIFEST'" '(974 characters)'
  35. if test -f 'MANIFEST' ; then 
  36.   echo shar: will not over-write existing file "'MANIFEST'"
  37. else
  38. sed 's/^X//' >MANIFEST <<'@//E*O*F MANIFEST//'
  39. X  File Name             Kit #   Description
  40. X-----------------------------------------------------------
  41. X MANIFEST                  1
  42. X README                    1
  43. X config.h                  1
  44. X digest.c                  1
  45. X envir_set.c               1
  46. X groupdir.c                1
  47. X hash.c                    1
  48. X head.h                    1
  49. X mf.nore                   1
  50. X mf.re                     1
  51. X mf.sysv                   1
  52. X newsrc.c                  1
  53. X pagefile.c                1
  54. X reader.c                  2
  55. X reader.h                  1
  56. X reg.c                     1
  57. X sig_set.c                 1
  58. X storage.c                 1
  59. X strings.c                 1
  60. X strtok.c                  2
  61. X term_set.c                2
  62. X tmpnam.c                  1
  63. X tty.h                     2
  64. X tty_set.c                 2
  65. X tune.h                    2
  66. X userlist.c                2
  67. X vn.c                      3
  68. X vn.h                      2
  69. X vn.man                    3
  70. X vnglob.c                  2
  71. @//E*O*F MANIFEST//
  72. if test 974 -ne "`wc -c <'MANIFEST'`"; then
  73.     echo shar: error transmitting "'MANIFEST'" '(should have been 974 characters)'
  74. fi
  75. fi # end of overwriting check
  76. echo shar: extracting "'README'" '(7590 characters)'
  77. if test -f 'README' ; then 
  78.   echo shar: will not over-write existing file "'README'"
  79. else
  80. sed 's/^X//' >README <<'@//E*O*F README//'
  81. XInstallation procedure steps:
  82. X
  83. X1) Edit file config.h, which defines system dependent parameters such as
  84. Xspool directory, and so on.  I have NOT ifdef'ed this file for likely
  85. Xchanges for SYSV or anything like that.  You probably can use this file
  86. Xuntouched only if you are UCB with news installed in all the standard places.
  87. XEven then, you may not like some of the defaults.
  88. X
  89. XNote very carefully the definitions involving mailer treatment.
  90. X
  91. X2) decide which makefile to use, edit it to fill in the correct libraries
  92. Xfor your system.  See notes 2) below for explanation.
  93. X
  94. X3) make vn
  95. X
  96. X4) put the executable where you want it.  put the man page, vn.man
  97. Xwhere you want it.  roff it with -man to print it out.  If you made
  98. Xsome configuration changes, or you are a SYSV installation, you may
  99. Xwant to modify the manual a bit.  It is written to reflect the actions in
  100. Xthe config.h as distributed, and as used on UCB (it refers to job control).
  101. X
  102. XNotes:
  103. X
  104. X1)
  105. X    If you modify the default mailer, poster, printer or editor, this is
  106. X    their invocation, ufile being a tempfile name.
  107. X
  108. X    "mailer [path] <ufile" - path obtained from newsarticle, possibly
  109. X        modified by user.  May be invoked with no argument dependent
  110. X        on how you set up config.h.  No path argument if INLETTER.
  111. X    "poster <ufile" - thus the "inews -h" to get header lines from
  112. X        file, giving user a chance to modify headers.
  113. X    "printer files 2>/dev/null"
  114. X    "editor ufile"
  115. X
  116. X    You may also be interested in the header file "tune.h" which contains
  117. X    some sizing / performance affecting parameters.
  118. X
  119. X2)
  120. X    There are three makefile templates, all very simple, because I
  121. X    want to make you think about whether you have the system V regular
  122. X    expression library, and strtok() or not.  If you have regex and
  123. X    regcmp (as opposed to re_exec and re_comp, the ucb regular
  124. X    expression library), I advise you to use them.  regex and
  125. X    regcmp are used because they have the ability to keep several
  126. X    regular expressions compiled at once.  The file "reg.c" is an
  127. X    implementation of regcmp and regex on top of the ucb calls,
  128. X    with a special procedure called "regfree" used in place of the
  129. X    generic "free" call used with regcmp / regex.  Use the system V
  130. X    calls if you have them available because:
  131. X
  132. X        i) They should be faster than the reg.c code, which
  133. X        recompiles the "current" ucb string every time you
  134. X        switch regular expressions.
  135. X
  136. X        ii) I briefly checked out reg.c once, and it seemed to
  137. X        work.  Our system has the "real" calls available, so I
  138. X        run with those.  reg.c hasn't been used much by me, although
  139. X        I've had nobody tell me it doesn't work.
  140. X
  141. X    strtok.c defines the strtok() and strpbrk() functions.  As with
  142. X    regex, if you have system libraries, they are likely more efficient -
  143. X    these string routines will often be done in assembler on a given
  144. X    machine.
  145. X
  146. X    tmpnam.c defines the tmpnam() routine.  Even if a BSD system has it,
  147. X    you might use it anyhow.  We are currently running under Ultrix on a
  148. X    microvax, and in fact, the Ultrix version doesn't work right (as of
  149. X    the last time I checked).  Also, the tmpnam.c version will produce
  150. X    temp files named vnXXXXXX, instead of a generic tmpXXXXXX.
  151. X
  152. X    There are 2 IFDEF's handled in the makefile templates:
  153. X
  154. X        SYSV - system V specific portions.
  155. X
  156. X        JOBCONTROL - brackets the parts dealing with the SIGTSTP
  157. X            signal handling for job control.  This could really
  158. X            be done with "#ifndef SYSV", I suppose, but this
  159. X            clearly marks this specific difference.
  160. X
  161. X    The ifdef OLDRC may be set to make the .newsrc format consistent
  162. X    with an apparently earlier readnews format which would not take
  163. X    ranges for "articles read".  This also makes -i an alias for a -x
  164. X    option, and assumes that any arguments with no options are really
  165. X    -n options.  These changes came from Australia, and are apparently
  166. X    compatible with whatever other newsreader was being used there.
  167. X
  168. X    SYSV, JOBCONTROL, OLDRC and the definitions referred to in config.h
  169. X    are the whole set.
  170. X
  171. X    If you are BSD but have regex/regcomp:
  172. X
  173. X        mf.re is the makefile template.  Fill in your local
  174. X        libraries (termcap), the library to find regex/regcmp in.
  175. X        This makefile defines "regfree" simply to be "free", and
  176. X        doesn't link the "reg" object.  JOBCONTROL defined.  This
  177. X        template also assumes you have strtok() / strpbrk().  If you
  178. X        don't, include strtok.o in the objects.  This is actually
  179. X        the makefile I use for Ultrix as given.
  180. X
  181. X    If you are BSD but don't have regex/regcomp:
  182. X
  183. X        mf.nore is the makefile template.  Fill in your local
  184. X        libraries (termcap).  This makefile pulls in the "reg"
  185. X        object.  JOBCONTROL defined.  If you DO have strtok() /
  186. X        strpbrk() available, you might remove strtok.o from the
  187. X        object list.
  188. X
  189. X    If you are SYS V:
  190. X
  191. X        mf.sysv is the makefile template.  Fill in your local
  192. X        libraries (termcap).  This makefile does not pull in
  193. X        the extra objects.  It defines "regfree" to "free", and
  194. X        turns the BSD index / rindex into strchr / strrchr.
  195. X        SYSV defined.
  196. X
  197. X        I haven't personally tried any SYSV stuff out - I don't have
  198. X        access to a SYS V machine running news.  You might want to
  199. X        include tmpnam.o in the object list instead of using the
  200. X        standard one, to get specifically named temp. files.
  201. X
  202. X    Something pretty close to the current vn version used to run here
  203. X    on a VAX 780 under BSD 4.2.
  204. X
  205. XNEWS VERSIONS:
  206. X
  207. XI know there's a lot of news versions running out there.  We seem to
  208. Xbe running something called B2.10.3, for those of you whom that signifies
  209. Xanything to.  Something to look at is your "active" file.  I expect to
  210. Xfind a newsgroup followed by the high, then low, spooling numbers (followed
  211. Xby a y/n for posting priveledge, which I don't care about).  Earlier news
  212. Xversions used to only have a single spooling number.  vn is written to
  213. Xhandle this, assuming 0 for a low spool.  My basic assumptions are that
  214. Xthe "active" file gives the newsgroups and spooling information and that
  215. Xarticles will be numeric filenames living in the directory obtained by
  216. Xreplacing periods with slashes in the newsgroup, and prefixing the spool
  217. Xdirectory.  I hope these really are "basic" assumptions that work across all
  218. Xversions.  vn is intended to be highly fault-tolerant regarding what it
  219. Xfinds for header lines - it may not be able to make sense out of an "article",
  220. Xbut it's willing to let you look at it anyway, with the single exception
  221. Xthat it throws away articles which turn out to be empty or 1 line files (
  222. XCOUNTING the header lines - articles with 0 lines in them are OK.  I'm
  223. Xjust preventing the "unknown subject, unknown author, and no text" case).
  224. X
  225. XRESOURCE USE:
  226. X
  227. Xvn should look like people sitting in an editor once it is done with its
  228. Xreading phase.  During the reading phase, it is beating mercilessly on
  229. Xthe spooling directory, reading file after file.  I have thought from time
  230. Xto time about having a daemon do this work periodically, building a master
  231. Xfile of title information for vn to access.  Its reading phase would then
  232. Xbe a "pause" rather than a "phase", with the penalty that you couldn't
  233. Xread anything until the daemon had gotten around to it.
  234. X
  235. Xvn maintains a large temporary file containing the users page screens.
  236. XAgain, it should look a lot like the user is using an editor which has
  237. Xa temp file out there for its edit buffer.  MAX_C in "tune.h" can be
  238. Xused to help control the size.
  239. X
  240. Xmalloc() usage - Around 50 bytes per newsgroup is dynamically allocated,
  241. Xplus storage for character strings and the current screen structure.
  242. XMy guess would be on the order of 20-40K.  It's all "permanent" information
  243. Xmaintained for the entire session, hence unfreed.  Regular expression
  244. Xstorage is freed, but is minimal anyway.
  245. @//E*O*F README//
  246. if test 7590 -ne "`wc -c <'README'`"; then
  247.     echo shar: error transmitting "'README'" '(should have been 7590 characters)'
  248. fi
  249. fi # end of overwriting check
  250. echo shar: extracting "'config.h'" '(3422 characters)'
  251. if test -f 'config.h' ; then 
  252.   echo shar: will not over-write existing file "'config.h'"
  253. else
  254. sed 's/^X//' >config.h <<'@//E*O*F config.h//'
  255. X/*
  256. X** vn news reader.
  257. X**
  258. X** config.h - system configuration parameters
  259. X**
  260. X** see copyright disclaimer / history in vn.c source file
  261. X*/
  262. X
  263. X#define DEF_ED "/usr/ucb/vi"    /* editor to use if no EDITOR variable */
  264. X#define DEF_PS1 "$ "        /* ! command prompt if no PS1 */
  265. X#define DEF_SAVE "vn.save"    /* save file */
  266. X
  267. X/*
  268. X** mailer interface.  If INLETTER is defined, a "To:" line will be
  269. X** placed in the file being editted by the user.  Otherwise, the
  270. X** address will be an argument on the mailer's command line, with the
  271. X** user prompted for possible correction.  In either case, "Subject: "
  272. X** is included in the file.
  273. X**
  274. X** If MAILSMART is set, alternate header lines will be used instead of
  275. X** the "Path: " line to determine the address because we assume the mailer
  276. X** is intelligent enough to do routing.
  277. X**
  278. X** If ADDRMUNGE is set, it is the name of a local routine which will be
  279. X** called to make further address modifications before the address is used.
  280. X** It will be passed the address string, which it may modify.  RECLEN bytes
  281. X** of storage are available at the address passed.  It will only be called
  282. X** once for a given address.
  283. X**
  284. X** DEF_MAIL is the mailer used in absence of MAILER variable.
  285. X*/
  286. X#define INLETTER
  287. X#define MAILSMART
  288. X#define DEF_MAIL "/usr/lib/sendmail -t"
  289. X
  290. X#define DEF_PRINT "/usr/ucb/lpr"        /* print command */
  291. X#define DEF_POST "/usr/lib/news/inews -h"    /* followup posting command */
  292. X
  293. X#define DEF_NEWSRC ".newsrc"
  294. X#define DEF_CCFILE "author_copy"
  295. X#define DEF_KEYXLN ".vnkey"
  296. X
  297. X#define SPOOLDIR "/usr/spool/news"
  298. X#define ACTFILE "/usr/lib/news/active"
  299. X
  300. X/*
  301. X** foreground flag for messages.  applies only if JOBCONTROL undefined
  302. X** (SYS V). set to 1 to see newsgroup messages, etc. during reading phase,
  303. X** 0 for "silent" operation - be warned that this may suppress some
  304. X** non-fatal diagnostic messages - find all references to fgprintf to
  305. X** see what is suppressed.
  306. X*/
  307. X#define NOJOB_FG 1
  308. X
  309. X/*
  310. X** arrow key treatment.  If PAGEARROW is defined, right and left arrow
  311. X** keys will be synonyms for <return> (next-page) and <backspace> (previous).
  312. X** Otherwise, the right arrow will function as down, and the left as up.
  313. X** Made configurable because while there is no lateral motion on the screen
  314. X** to associate with the right and left arrows, you might not like them
  315. X** changing pages on you.
  316. X*/
  317. X#define PAGEARROW
  318. X
  319. X/*
  320. X** if USEVS is defined, terminal initialization / exit for vn will include the
  321. X** "vs"/"ve" pair as well as "ti"/"te".  This doesn't matter on a lot of
  322. X** terminals, but may make vn display behaviour closer to "vi" since vs/ve
  323. X** is vi's "visual mode" sequence.  For instance, I believe the commonly
  324. X** used definitions for these strings on multi-page concepts allows the
  325. X** program to run in the first page of the terminal, preserving the more
  326. X** recent part of your session on exit
  327. X**
  328. X** #define USEVS
  329. X*/
  330. X
  331. X/*
  332. X** temp file name template for mktemp().  Used in tmpnam.c, does not apply
  333. X** if you use a system library tmpnam().   BE CAREFUL - VNTEMPNAME MUST
  334. X** contain a string of 6 X's for mktemp() (actually, a place where 6 X's
  335. X** are intended to go).  TMP_XOFFSET absolutely MUST point to the first of
  336. X** the X's.  Yes, writing into a literal string is sloppy.  To the best of
  337. X** my knowledge, tmpnam.c is the only place you'll find vn code doing it.
  338. X** We make this configurable in case you want temp files somewhere else.
  339. X*/
  340. X#define VNTEMPNAME "/usr/tmp/vnXXXXXX"
  341. X#define TMP_XOFFSET 11
  342. @//E*O*F config.h//
  343. if test 3422 -ne "`wc -c <'config.h'`"; then
  344.     echo shar: error transmitting "'config.h'" '(should have been 3422 characters)'
  345. fi
  346. fi # end of overwriting check
  347. echo shar: extracting "'digest.c'" '(5027 characters)'
  348. if test -f 'digest.c' ; then 
  349.   echo shar: will not over-write existing file "'digest.c'"
  350. else
  351. sed 's/^X//' >digest.c <<'@//E*O*F digest.c//'
  352. X/*
  353. X** vn news reader.
  354. X**
  355. X** digest.c - digest unpacking routines
  356. X**
  357. X** see copyright disclaimer / history in vn.c source file
  358. X*/
  359. X
  360. X#include <stdio.h>
  361. X#include "config.h"
  362. X#include "vn.h"
  363. X#include "head.h"
  364. X
  365. Xextern int Digest;
  366. Xextern int L_allow;
  367. Xextern int C_allow;
  368. Xextern PAGE Page;
  369. X
  370. Xextern char *F_head, *T_head, *L_head, *D_head;
  371. X
  372. Xdigest_page (idx,skip)
  373. Xint idx;
  374. X{
  375. X    char *ptr,name[24],*title,*index();
  376. X    FILE *fp;
  377. X    int i,len;
  378. X    char subj[RECLEN],date[RECLEN],from[RECLEN],junk[RECLEN],*str_store();
  379. X    long pos;
  380. X
  381. X    Digest = Page.b[idx].art_id;
  382. X    sprintf (name,"%d", Digest);
  383. X
  384. X    if ((fp = fopen(name,"r")) == NULL)
  385. X        return (-1);
  386. X
  387. X    subj[0] = date[0] = from[0] = junk[0] = '\0';
  388. X
  389. X    skip_header (fp);
  390. X
  391. X    /* skip over some articles if requested to */
  392. X    for (i=skip; i > 0; --i)
  393. X    {
  394. X        if (dig_advance(fp,from,subj,date,junk,&pos) < 0)
  395. X            return (-1);
  396. X    }
  397. X
  398. X    /* every new call to a digest Page "loses" a small amount of storage */
  399. X    title = str_store(Page.b[idx].art_t);
  400. X    if ((ptr = index(title,'~')) != 0)
  401. X        *ptr = '\0';
  402. X    title [C_allow - 20] = '\0';
  403. X
  404. X    for (i=0; i < L_allow &&
  405. X            (len = dig_advance(fp,from,subj,date,junk,&pos)) >= 0; ++i)
  406. X    {
  407. X        Page.b[i].art_id = i+1+skip;
  408. X        Page.b[i].art_mark = ' ';
  409. X        subj [C_allow] = '\0';
  410. X        from [C_allow] = '\0';
  411. X        sprintf (name,"%d",len);
  412. X        form_title (date,subj,name,from,100);
  413. X        strcpy (Page.b[i].art_t,date);
  414. X    }
  415. X
  416. X    fclose (fp);
  417. X
  418. X    if (i == 0)
  419. X        return (-1);
  420. X
  421. X    Page.h.name = title;
  422. X    Page.h.artnum = i;
  423. X    return (i);
  424. X}
  425. X
  426. X/*
  427. X    returns name of file containing "article", NULL for failure
  428. X*/
  429. Xchar * digest_extract (s,art)
  430. Xchar *s;
  431. Xint art;
  432. X{
  433. X    char name[24];
  434. X    FILE *fout,*fin;
  435. X    char subj[RECLEN],date[RECLEN],from[RECLEN],bufr[RECLEN];
  436. X    char extra[RECLEN];
  437. X    char *index();
  438. X    long pos;
  439. X    int lines;
  440. X
  441. X    sprintf (name,"%d", Digest);
  442. X    if ((fin = fopen(name,"r")) == NULL)
  443. X        return (NULL);
  444. X
  445. X    for (skip_header (fin); art > 0; --art)
  446. X        if ((lines = dig_advance(fin,from,subj,date,extra,&pos)) < 0)
  447. X        {
  448. X            fclose (fin);
  449. X            return (NULL);
  450. X        }
  451. X
  452. X    tmpnam(s);
  453. X
  454. X    if ((fout = fopen(s,"w")) == NULL)
  455. X    {
  456. X        fclose (fin);
  457. X        unlink (s);
  458. X        return (NULL);
  459. X    }
  460. X
  461. X    fseek(fin,0L,0);
  462. X
  463. X    while (fgets(bufr,RECLEN-1,fin) != NULL && index(bufr,':') != NULL)
  464. X    {
  465. X        if (strncmp(bufr,F_head,FHDLEN) == 0)
  466. X        {
  467. X            fprintf (fout,"%s%s\n",F_head,from);
  468. X            continue;
  469. X        }
  470. X        if (strncmp(bufr,T_head,THDLEN) == 0)
  471. X        {
  472. X            fprintf (fout,"%s%s\n",T_head,subj);
  473. X            continue;
  474. X        }
  475. X        if (strncmp(bufr,D_head,DHDLEN) == 0)
  476. X        {
  477. X            fprintf (fout,"%s%s\n",D_head,date);
  478. X            continue;
  479. X        }
  480. X        /* defer line count header - it comes last */
  481. X        if (strncmp(bufr,L_head,LHDLEN) == 0)
  482. X            continue;
  483. X        fprintf (fout,"%s",bufr);
  484. X    }
  485. X
  486. X    /* toss in extra header lines, line count header, extra newline */
  487. X    fprintf (fout,"%s%s%d\n\n",extra,L_head,lines);
  488. X
  489. X    fseek (fin,pos,0);
  490. X
  491. X    while (fgets(bufr,RECLEN-1,fin) != NULL && strncmp(bufr,"--------",8) != 0)
  492. X        fprintf(fout,"%s",bufr);
  493. X
  494. X    fclose (fin);
  495. X    fclose (fout);
  496. X    return (s);
  497. X}
  498. X
  499. Xdig_list (s)
  500. Xchar *s;
  501. X{
  502. X    char *ptr,*out,*new,ns[L_tmpnam],tmp[RECLEN],*strtok();
  503. X    int i;
  504. X
  505. X    prinfo ("Extracting articles .....");
  506. X    strcpy (tmp,s);
  507. X    out = s;
  508. X
  509. X    for (ptr = strtok(tmp," "); ptr != NULL; ptr = strtok(NULL," "))
  510. X    {
  511. X        i = atoi(ptr);
  512. X        if ((new = digest_extract(ns,i)) != NULL)
  513. X        {
  514. X            sprintf (out,"%s ",new);
  515. X            out += strlen(new) + 1;
  516. X        }
  517. X    }
  518. X
  519. X    *out = '\0';
  520. X
  521. X    if (*s == '\0')
  522. X        strcpy (s,"NULLDIGEST");
  523. X}
  524. X
  525. Xdig_ulist (s)
  526. Xchar *s;
  527. X{
  528. X    char *strtok();
  529. X    for (s = strtok(s," "); s != NULL; s = strtok(NULL," "))
  530. X        unlink (s);
  531. X}
  532. X
  533. X/*
  534. X    returns # lines in article, -1 for failure
  535. X    scans past article, returns position of start.
  536. X    also returns "extra" header lines encountered, WITH newlines.
  537. X*/
  538. Xstatic dig_advance (fp,from,subj,date,extra,pos)
  539. XFILE *fp;
  540. Xchar *from,*subj,*date,*extra;
  541. Xlong *pos;
  542. X{
  543. X    char buf[RECLEN];
  544. X    char *ptr, *index();
  545. X    int len,state,lcount;
  546. X
  547. X    lcount = state = 0;
  548. X    *extra = '\0';
  549. X
  550. X    while (fgets(buf,RECLEN-1,fp) != NULL)
  551. X    {
  552. X        buf[(len = strlen(buf) - 1)] = '\0';
  553. X        for (--len ; len >= 0 && buf[len] == ' ' || buf[len] == '\t'; --len)
  554. X            buf[len] = '\0';
  555. X        ++len;
  556. X
  557. X        switch(state)
  558. X        {
  559. X        case 0:
  560. X            /* skip blank lines before header */
  561. X            if (len == 0)
  562. X                break;
  563. X            state = 1;    /* fall through */
  564. X        case 1:
  565. X            if (strncmp(buf,F_head,FHDLEN) == 0)
  566. X            {
  567. X                strcpy (from,buf+FHDLEN);
  568. X                break;
  569. X            }
  570. X            if (strncmp(buf,T_head,THDLEN) == 0)
  571. X            {
  572. X                strcpy (subj,buf+THDLEN);
  573. X                break;
  574. X            }
  575. X            if (strncmp(buf,D_head,DHDLEN) == 0)
  576. X            {
  577. X                strcpy (date,buf+DHDLEN);
  578. X                break;
  579. X            }
  580. X            /* put wierd header lines in extra */
  581. X            if ((ptr = index(buf,':')) != NULL)
  582. X            {
  583. X                *ptr = '\0';
  584. X                if (index(buf, ' ') == NULL)
  585. X                {
  586. X                    *ptr = ':';
  587. X                    sprintf(extra,"%s\n",buf);
  588. X                    extra += strlen(extra);
  589. X                    break;
  590. X                }
  591. X                *ptr = ':';
  592. X            }
  593. X            state = 2;
  594. X
  595. X            /* remember the newline we lopped off */
  596. X            *pos = ftell(fp)-strlen(buf)-1;    /* fall through */
  597. X        case 2:
  598. X            ++lcount;
  599. X            if (strncmp("--------",buf,8) == 0)
  600. X            {
  601. X                --lcount;
  602. X                return (lcount);
  603. X            }
  604. X            break;
  605. X        }
  606. X    }
  607. X
  608. X    return (-1);
  609. X}
  610. X
  611. Xstatic skip_header (fp)
  612. XFILE *fp;
  613. X{
  614. X    char buf[RECLEN];
  615. X
  616. X    while (fgets(buf,RECLEN-1,fp) != NULL)
  617. X        if (strncmp("--------",buf,8) == 0)
  618. X            break;
  619. X}
  620. @//E*O*F digest.c//
  621. if test 5027 -ne "`wc -c <'digest.c'`"; then
  622.     echo shar: error transmitting "'digest.c'" '(should have been 5027 characters)'
  623. fi
  624. fi # end of overwriting check
  625. echo shar: extracting "'envir_set.c'" '(2931 characters)'
  626. if test -f 'envir_set.c' ; then 
  627.   echo shar: will not over-write existing file "'envir_set.c'"
  628. else
  629. sed 's/^X//' >envir_set.c <<'@//E*O*F envir_set.c//'
  630. X/*
  631. X** vn news reader.
  632. X**
  633. X** envir_set.c - routine to obtain pertinent environment variable settings
  634. X**        and set up file / directory names
  635. X**
  636. X** see copyright disclaimer / history in vn.c source file
  637. X*/
  638. X
  639. X#include <stdio.h>
  640. X#include <pwd.h>
  641. X#include <sys/param.h>
  642. X#include "config.h"
  643. X
  644. Xextern char *Editor,*Ps1,*Mailer,*Printer,*Poster;
  645. Xextern char *Onews, *Newsrc, *Orgdir, *Savedir, *Ccfile;    /* path names */
  646. Xextern char Cxitop[], Cxitor[], Cxrtoi[], Cxptoi[];
  647. X
  648. X#ifdef SYSV
  649. Xextern char *getcwd();
  650. X#define getwd(a) getcwd(a,sizeof(a))
  651. X#define    MAXPATHLEN 240
  652. X#else
  653. Xextern char *getwd();
  654. X#endif
  655. X
  656. X/*
  657. X    environment variable, original directory string setup.
  658. X*/
  659. X
  660. Xenvir_set ()
  661. X{
  662. X     char dbuf [MAXPATHLEN], *rcname, *ccname, *keyxln;
  663. X    char *getenv(), *getcwd(), *str_store();
  664. X    struct passwd *ptr, *getpwuid();
  665. X
  666. X    if ((Ps1 = getenv("PS1")) == NULL)
  667. X        Ps1 = DEF_PS1;
  668. X    if ((Editor = getenv("EDITOR")) == NULL)
  669. X        Editor=DEF_ED;
  670. X    if ((Mailer = getenv("MAILER")) == NULL)
  671. X        Mailer=DEF_MAIL;
  672. X    if ((Poster = getenv("POSTER")) == NULL)
  673. X        Poster=DEF_POST;
  674. X    if ((Printer = getenv("PRINTER")) == NULL)
  675. X        Printer=DEF_PRINT;
  676. X    if ((rcname = getenv("NEWSRC")) == NULL)
  677. X        rcname=DEF_NEWSRC;
  678. X    if ((ccname = getenv("CCFILE")) == NULL)
  679. X        ccname=DEF_CCFILE;
  680. X    if ((keyxln = getenv("VNKEY")) == NULL)
  681. X        keyxln=DEF_KEYXLN;
  682. X    Savedir = getenv("VNSAVE");
  683. X
  684. X    /*
  685. X        set original directory strings.  create empty Newsrc if it doesn't exist
  686. X    */
  687. X
  688. X    ptr = getpwuid (getuid());
  689. X    if ((Orgdir = getwd(dbuf)) == NULL)
  690. X        printex ("cannot stat pwd");
  691. X    Orgdir = str_store (Orgdir);
  692. X    if (Savedir == NULL)
  693. X        Savedir = Orgdir;
  694. X    if (*rcname != '/')
  695. X    {
  696. X        sprintf (dbuf, "%s/%s",ptr->pw_dir,rcname);
  697. X        Newsrc = str_store (dbuf);
  698. X    }
  699. X    else
  700. X        Newsrc = str_store (rcname);
  701. X    if (*ccname != '/')
  702. X    {
  703. X        sprintf (dbuf, "%s/%s",ptr->pw_dir,ccname);
  704. X        Ccfile = str_store (dbuf);
  705. X    }
  706. X    else
  707. X        Ccfile = str_store (ccname);
  708. X    sprintf (dbuf, "%s/%s%s",ptr->pw_dir,".vn","XXXXXX");
  709. X    Onews = str_store (mktemp(dbuf));
  710. X    if (access (Newsrc,0) != 0)
  711. X        creat (Newsrc,0666);
  712. X
  713. X    if (*keyxln != '/')
  714. X    {
  715. X        sprintf(dbuf, "%s/%s",ptr->pw_dir,keyxln);
  716. X        set_kxln(dbuf);
  717. X    }
  718. X    else
  719. X        set_kxln(keyxln);
  720. X}
  721. X
  722. Xstatic
  723. Xset_kxln(fname)
  724. Xchar *fname;
  725. X{
  726. X    FILE *fp;
  727. X    int i;
  728. X    char bufr[80];
  729. X    char in,out,*ptr;
  730. X    char *index(), xln_str();
  731. X
  732. X    for (i=0; i < 128; ++i)
  733. X        Cxitop[i] = Cxitor[i] = Cxptoi[i] = Cxrtoi[i] = i;
  734. X
  735. X    if ((fp = fopen(fname,"r")) != NULL)
  736. X    {
  737. X        while(fgets(bufr,79,fp) != NULL)
  738. X        {
  739. X            if (strncmp(bufr+1,"==",2) == 0)
  740. X                ptr = bufr+2;
  741. X            else
  742. X                ptr = index(bufr+1,'=');
  743. X            if (ptr == NULL)
  744. X                continue;
  745. X            *ptr = '\0';
  746. X            ++ptr;
  747. X            in = xln_str(bufr+1);
  748. X            out = xln_str(ptr);
  749. X            switch(bufr[0])
  750. X            {
  751. X            case 'r':
  752. X            case 'R':
  753. X                Cxrtoi[out] = in;
  754. X                Cxitor[in] = out;
  755. X                break;
  756. X            case 'p':
  757. X            case 'P':
  758. X                Cxptoi[out] = in;
  759. X                Cxitop[in] = out;
  760. X            default:
  761. X                break;
  762. X            }
  763. X        }
  764. X        fclose(fp);
  765. X    }
  766. X}
  767. X
  768. Xstatic char
  769. Xxln_str(s)
  770. Xchar *s;
  771. X{
  772. X    if (*s < '0' || *s > '9')
  773. X        return(*s & 0x7f);
  774. X    return((char)(atoi(s) & 0x7f));
  775. X}
  776. @//E*O*F envir_set.c//
  777. if test 2931 -ne "`wc -c <'envir_set.c'`"; then
  778.     echo shar: error transmitting "'envir_set.c'" '(should have been 2931 characters)'
  779. fi
  780. fi # end of overwriting check
  781. echo shar: extracting "'groupdir.c'" '(686 characters)'
  782. if test -f 'groupdir.c' ; then 
  783.   echo shar: will not over-write existing file "'groupdir.c'"
  784. else
  785. sed 's/^X//' >groupdir.c <<'@//E*O*F groupdir.c//'
  786. X/*
  787. X** vn news reader.
  788. X**
  789. X** groupdir.c - translation between newsgroup name and directory
  790. X**
  791. X** see copyright disclaimer / history in vn.c source file
  792. X*/
  793. X
  794. X#include <stdio.h>
  795. X#include "config.h"
  796. X#include "vn.h"
  797. X
  798. Xextern PAGE Page;
  799. X
  800. X/*
  801. X    g_dir converts newsgroup name to directory string
  802. X*/
  803. Xg_dir(s,t)
  804. Xchar *s,*t;
  805. X{
  806. X    char *ptr, *index();
  807. X    sprintf (t,"%s/%s",SPOOLDIR,s);
  808. X    for (ptr=t+strlen(SPOOLDIR)+1; (ptr = index(ptr,'.')) != NULL; *ptr = '/')
  809. X        ;
  810. X}
  811. X
  812. X
  813. X/*
  814. X    change directory to group
  815. X*/
  816. Xcd_group ()
  817. X{
  818. X    char dbuf [RECLEN];
  819. X    g_dir ((Page.h.group)->nd_name,dbuf);
  820. X    if (chdir(dbuf) < 0)
  821. X    {
  822. X        Page.h.artnum = 1;
  823. X        Page.b[0].art_id = 0;
  824. X        strcpy (Page.b[0].art_t, "CANNOT FIND NEWSGROUP");
  825. X    }
  826. X}
  827. @//E*O*F groupdir.c//
  828. if test 686 -ne "`wc -c <'groupdir.c'`"; then
  829.     echo shar: error transmitting "'groupdir.c'" '(should have been 686 characters)'
  830. fi
  831. fi # end of overwriting check
  832. echo shar: extracting "'hash.c'" '(1842 characters)'
  833. if test -f 'hash.c' ; then 
  834.   echo shar: will not over-write existing file "'hash.c'"
  835. else
  836. sed 's/^X//' >hash.c <<'@//E*O*F hash.c//'
  837. X/*
  838. X** vn news reader.
  839. X**
  840. X** hash.c - hash table routines
  841. X**
  842. X** see copyright disclaimer / history in vn.c source file
  843. X*/
  844. X
  845. X#include <stdio.h>
  846. X#include "config.h"
  847. X#include "tune.h"
  848. X#include "vn.h"
  849. X
  850. X/*
  851. X** hash table manipulation routines:
  852. X**    also sets Ncount, allocates Newsorsder array, and sets Newsorder
  853. X**    initially to order newsgroups were entered in (active file order)
  854. X*/
  855. X
  856. Xextern int Ncount;
  857. Xextern NODE **Newsorder;
  858. X
  859. Xstatic NODE *Tab [HASHSIZE];    /* hash Table */
  860. X
  861. Xhashinit ()
  862. X{
  863. X    int i;
  864. X    for (i=0; i < HASHSIZE; ++i)
  865. X        Tab[i] = NULL;
  866. X    Ncount = 0;
  867. X}
  868. X
  869. X/*
  870. X    enter new node (name s, articles n, low l) in hash Table, 
  871. X    initial flags = 0.  As nodes are entered, pnum item is temporarily
  872. X    used to indiacte entry order for initial construction of Newsorder
  873. X    array via entry_order();
  874. X*/
  875. XNODE *hashenter(s,n,l)
  876. Xchar *s;
  877. Xint n;
  878. Xint l;
  879. X{
  880. X    char *str_store();
  881. X    NODE *ptr,*node_store();
  882. X    int i;
  883. X
  884. X    i=hash(s);
  885. X    ptr = node_store();
  886. X    ptr->next = Tab[i];
  887. X    Tab[i] = ptr;
  888. X    if (l > n)
  889. X        l = n;
  890. X    ptr->pnum = Ncount;
  891. X    ++Ncount;
  892. X    ptr->rdnum = l;
  893. X    ptr->state = 0;
  894. X    ptr->art = n;
  895. X    ptr->nd_name = str_store(s);
  896. X    return (ptr);
  897. X}
  898. X
  899. XNODE *hashfind(s)
  900. Xchar *s;
  901. X{
  902. X    NODE *ptr;
  903. X
  904. X    for (ptr = Tab[hash(s)]; ptr != NULL && strcmp(ptr->nd_name,s) != 0;
  905. X                    ptr = ptr->next)
  906. X            ;
  907. X    return (ptr);
  908. X}
  909. X
  910. X/*
  911. X** entry order is called after all hash_enter's have been done, PRIOR
  912. X** to the use of pnum item for anything else.  It constructs the initial
  913. X** Newsorder array.
  914. X*/
  915. Xentry_order()
  916. X{
  917. X    int i;
  918. X    NODE *ptr;
  919. X
  920. X    if ((Newsorder = (NODE **) malloc(Ncount*sizeof(NODE *))) == NULL)
  921. X        printex("Cannot allocate memory for Newsorder array");
  922. X    for (i=0; i < HASHSIZE; ++i)
  923. X    {
  924. X        for (ptr = Tab[i]; ptr != NULL; ptr = ptr->next)
  925. X            Newsorder[ptr->pnum] = ptr;
  926. X    }
  927. X}
  928. X
  929. Xstatic hash (s)
  930. Xchar *s;
  931. X{
  932. X    int rem;
  933. X    for (rem=0; *s != '\0'; ++s)
  934. X        rem = (rem*128 + (*s&0x7f)) % HASHSIZE;
  935. X    return (rem);
  936. X}
  937. @//E*O*F hash.c//
  938. if test 1842 -ne "`wc -c <'hash.c'`"; then
  939.     echo shar: error transmitting "'hash.c'" '(should have been 1842 characters)'
  940. fi
  941. fi # end of overwriting check
  942. echo shar: extracting "'head.h'" '(839 characters)'
  943. if test -f 'head.h' ; then 
  944.   echo shar: will not over-write existing file "'head.h'"
  945. else
  946. sed 's/^X//' >head.h <<'@//E*O*F head.h//'
  947. X/*
  948. X** vn news reader.
  949. X**
  950. X** head.h - header line strings and lengths
  951. X**
  952. X** see copyright disclaimer / history in vn.c source file
  953. X*/
  954. X
  955. X/*
  956. X    header lines and associated lengths.  Strings should
  957. X    actually be used once in strings.c.
  958. X*/ 
  959. X#define RHEAD "References: "
  960. X#define RHDLEN 12
  961. X#define MHEAD "Message-ID: "
  962. X#define MHDLEN 12
  963. X#define PHEAD "Path: "
  964. X#define PHDLEN 6
  965. X#define DHEAD "Date: "
  966. X#define DHDLEN 6
  967. X#define RTHEAD "Reply-To: "
  968. X#define RTHDLEN 10
  969. X#define TOHEAD "To: "
  970. X#define TOHDLEN 4
  971. X#define FHEAD "From: "
  972. X#define FHDLEN 6
  973. X#define FTHEAD "Followup-To: "
  974. X#define FTHDLEN 13
  975. X#define DISHEAD "Distribution: "
  976. X#define DISHDLEN 14
  977. X#define THEAD "Subject: "
  978. X#define THDLEN 9
  979. X#define LHEAD "Lines: "
  980. X#define LHDLEN 7
  981. X#define NHEAD "Newsgroups: "
  982. X#define NHDLEN 12
  983. X
  984. X#define CHFIRST "FSL"    /* first char's of those used in page display */
  985. @//E*O*F head.h//
  986. if test 839 -ne "`wc -c <'head.h'`"; then
  987.     echo shar: error transmitting "'head.h'" '(should have been 839 characters)'
  988. fi
  989. fi # end of overwriting check
  990. echo shar: extracting "'mf.nore'" '(254 characters)'
  991. if test -f 'mf.nore' ; then 
  992.   echo shar: will not over-write existing file "'mf.nore'"
  993. else
  994. sed 's/^X//' >mf.nore <<'@//E*O*F mf.nore//'
  995. XCFLAGS=    -O -DJOBCONTROL
  996. XLIBS= -ltermcap
  997. X
  998. XOBJS=    hash.o groupdir.o envir_set.o newsrc.o pagefile.o reader.o storage.o sig_set.o term_set.o tty_set.o userlist.o vn.o vnglob.o digest.o strings.o tmpnam.o reg.o strtok.o
  999. X
  1000. Xvn:    $(OBJS)
  1001. X    cc -o vn $(OBJS) $(LIBS)
  1002. @//E*O*F mf.nore//
  1003. if test 254 -ne "`wc -c <'mf.nore'`"; then
  1004.     echo shar: error transmitting "'mf.nore'" '(should have been 254 characters)'
  1005. fi
  1006. fi # end of overwriting check
  1007. echo shar: extracting "'mf.re'" '(272 characters)'
  1008. if test -f 'mf.re' ; then 
  1009.   echo shar: will not over-write existing file "'mf.re'"
  1010. else
  1011. sed 's/^X//' >mf.re <<'@//E*O*F mf.re//'
  1012. XCFLAGS=    -O -Dregfree=free -DJOBCONTROL
  1013. XREGLIB=
  1014. XLIBS= -ltermcap
  1015. X
  1016. XOBJS=    hash.o groupdir.o envir_set.o newsrc.o pagefile.o reader.o storage.o sig_set.o term_set.o tty_set.o userlist.o vn.o vnglob.o digest.o strings.o tmpnam.o
  1017. X
  1018. Xvn:    $(OBJS)
  1019. X    cc -o vn $(OBJS) $(LIBS) $(REGLIB)
  1020. @//E*O*F mf.re//
  1021. if test 272 -ne "`wc -c <'mf.re'`"; then
  1022.     echo shar: error transmitting "'mf.re'" '(should have been 272 characters)'
  1023. fi
  1024. fi # end of overwriting check
  1025. echo shar: extracting "'mf.sysv'" '(271 characters)'
  1026. if test -f 'mf.sysv' ; then 
  1027.   echo shar: will not over-write existing file "'mf.sysv'"
  1028. else
  1029. sed 's/^X//' >mf.sysv <<'@//E*O*F mf.sysv//'
  1030. XCFLAGS=    -O -Dregfree=free -Dindex=strchr -Drindex=strrchr -DSYSV
  1031. XLIBS= -ltermcap
  1032. X
  1033. XOBJS=    hash.o groupdir.o envir_set.o newsrc.o pagefile.o reader.o storage.o sig_set.o term_set.o tty_set.o userlist.o vn.o vnglob.o digest.o strings.o
  1034. X
  1035. Xvn:    $(OBJS)
  1036. X    cc -o vn $(OBJS) $(LIBS)
  1037. @//E*O*F mf.sysv//
  1038. if test 271 -ne "`wc -c <'mf.sysv'`"; then
  1039.     echo shar: error transmitting "'mf.sysv'" '(should have been 271 characters)'
  1040. fi
  1041. fi # end of overwriting check
  1042. echo shar: extracting "'newsrc.c'" '(11576 characters)'
  1043. if test -f 'newsrc.c' ; then 
  1044.   echo shar: will not over-write existing file "'newsrc.c'"
  1045. else
  1046. sed 's/^X//' >newsrc.c <<'@//E*O*F newsrc.c//'
  1047. X/*
  1048. X** vn news reader.
  1049. X**
  1050. X** newsrc.c - routines to deal with the newsrc file
  1051. X**
  1052. X** see copyright disclaimer / history in vn.c source file
  1053. X*/
  1054. X
  1055. X#include <stdio.h>
  1056. X#include <ctype.h>
  1057. X#include "config.h"
  1058. X#include "tty.h"
  1059. X#include "vn.h"
  1060. X
  1061. Xextern NODE **Newsorder;
  1062. Xextern char *Onews, *Newsrc;
  1063. Xextern int Ncount, Lrec, C_allow;
  1064. Xextern int Ntopt, Nntopt, Nwopt, Nnwopt;
  1065. Xextern char *Topt[], *Negtopt[], *Wopt[], *Negwopt[];
  1066. Xextern int Nounsub, Listfirst;
  1067. X
  1068. X/*
  1069. X    global flags signifying options set
  1070. X*/
  1071. X#define GF_ALL 1    /* -x option - scan everything */
  1072. X#define GF_SPEC 2    /* -n option(s) - user specified groups */
  1073. X#define GF_OVER 4    /* command line specification - overide marks */
  1074. X
  1075. Xstatic char *Options[OPTLINES];
  1076. Xstatic int New_idx, Max_name, Optlines;
  1077. Xstatic unsigned Gflags = 0;
  1078. X
  1079. X/*
  1080. X    routines for dealing with the .newsrc file and options
  1081. X*/
  1082. X
  1083. X/*
  1084. X    command name argument is already omitted from argv argc in this
  1085. X    routine.  Only the option arguments are present.  We process
  1086. X    options before we scan the rest of .newsrc, which redoes Newsorder,
  1087. X    ie. we don't clobber Ncount until options are processed.
  1088. X*/
  1089. Xscan_newsrc (argc,argv)
  1090. Xint argc;
  1091. Xchar **argv;
  1092. X{
  1093. X    FILE *fp, *fopen();
  1094. X    static char marks[] =
  1095. X    { 
  1096. X        NEWS_ON, NEWS_OFF, '\0' 
  1097. X    };
  1098. X    char *str_store ();
  1099. X    int line, len, num;
  1100. X    char buf [RECLEN], trail, optpflag, submark, *fret, *ptr, *strpbrk(), *strtok();
  1101. X
  1102. X
  1103. X    /* initialize hash table, open temp file, fill table with active articles */
  1104. X    hashinit ();
  1105. X    fill_active ();
  1106. X    temp_open();
  1107. X
  1108. X    if (argc > 0)
  1109. X    {
  1110. X        Gflags |= GF_OVER;
  1111. X        arg_opt(argc,argv);
  1112. X        optpflag = 'y';
  1113. X    }
  1114. X    else
  1115. X        optpflag = 'n';
  1116. X
  1117. X    if ((fp = fopen (Newsrc,"r")) == NULL)
  1118. X        printex ("can't open %s for reading",Newsrc);
  1119. X
  1120. X    Optlines = 0;
  1121. X
  1122. X    for (line = 1; (fret = fgets(buf,RECLEN-1,fp)) != NULL && emptyline(buf) == 1; ++line)
  1123. X        ;
  1124. X    if (fret != NULL && strncmp (buf,"options",7) == 0)
  1125. X    {
  1126. X        Options[0] = str_store(buf);
  1127. X        Optlines = 1;
  1128. X        trail = buf [strlen(buf)-2];
  1129. X        for ( ; (fret = fgets(buf,RECLEN-1,fp)) != NULL; ++line)
  1130. X        {
  1131. X            if (trail != '\\' && buf[0] != ' ' && buf[0] != '\t')
  1132. X                break;
  1133. X            if (Optlines >= OPTLINES)
  1134. X                printex ("%s - too many option lines (%d allowed)",Newsrc,OPTLINES);
  1135. X            Options[Optlines] = str_store(buf);
  1136. X            ++Optlines;
  1137. X            if ((len = strlen(buf)) >= 2 && buf[len-2] != '\\')
  1138. X                trail = buf[len-2];
  1139. X            else
  1140. X                trail = '\0';
  1141. X        }
  1142. X    }
  1143. X
  1144. X    /* do the options from the newsrc file if there weren't command line args */
  1145. X    if (Optlines > 0 && optpflag == 'n')
  1146. X        newsrc_opt ();
  1147. X
  1148. X    Ncount = 0;
  1149. X
  1150. X    for ( ; fret != NULL; ++line, fret = fgets(buf,RECLEN-1,fp))
  1151. X    {
  1152. X        if (emptyline(buf) == 1)
  1153. X            continue;
  1154. X        if ((ptr = strpbrk(buf,marks)) == NULL)
  1155. X        {
  1156. X            fprintf (stderr,"\nwarning: line %d of %s (%s) - bad syntax\n",
  1157. X            line,Newsrc,buf);
  1158. X            continue;
  1159. X        }
  1160. X        submark = *ptr;
  1161. X        *ptr = '\0';
  1162. X        ++ptr;
  1163. X        num = 0;
  1164. X        for (ptr = strtok(ptr," ,-\n"); ptr != NULL; ptr = strtok(NULL," ,-\n"))
  1165. X        {
  1166. X            len = atoi (ptr);
  1167. X            for ( ; *ptr >= '0' && *ptr <= '9'; ++ptr)
  1168. X                ;
  1169. X            if (*ptr != '\0' || len < num)
  1170. X            {
  1171. X                num = -1;
  1172. X                fprintf (stderr,"\nwarning: line %d of %s (%s) - bad syntax\n",
  1173. X                line,Newsrc,buf);
  1174. X                break;
  1175. X            }
  1176. X            num = len;
  1177. X        }
  1178. X        if (num < 0)
  1179. X            continue;
  1180. X        chkgroup (buf,submark,num);
  1181. X    }
  1182. X    fclose (fp);
  1183. X
  1184. X    /* now take care of groups not specified in .newsrc */
  1185. X    art_active();
  1186. X
  1187. X    /* free up the option string storage */
  1188. X    for (num=0; num < Ntopt; ++num)
  1189. X        regfree (Topt[num]);
  1190. X    for (num=0; num < Nwopt; ++num)
  1191. X        regfree (Wopt[num]);
  1192. X    for (num=0; num < Nntopt; ++num)
  1193. X        regfree (Negtopt[num]);
  1194. X    for (num=0; num < Nnwopt; ++num)
  1195. X        regfree (Negwopt[num]);
  1196. X    Ntopt = Nwopt = Nntopt = Nnwopt = 0;
  1197. X}
  1198. X
  1199. Xstatic emptyline(s)
  1200. Xchar *s;
  1201. X{
  1202. X    while (isspace(*s))
  1203. X        ++s;
  1204. X    if (*s == '\0')
  1205. X        return (1);
  1206. X    return (0);
  1207. X}
  1208. X
  1209. X/*
  1210. X    fill hash table from active news group list
  1211. X    temporarily makes "Newsorder" active list order.
  1212. X    This is needed to be able to process options
  1213. X    before scanning user order.
  1214. X*/
  1215. Xstatic fill_active ()
  1216. X{
  1217. X    FILE *f,*fopen ();
  1218. X    char *nread, act_rec[RECLEN], *strtok();
  1219. X    int num,lownum;
  1220. X
  1221. X    Max_name = 0;
  1222. X    if ((f = fopen (ACTFILE,"r")) == NULL)
  1223. X        printex ("couldn't open %s\n",ACTFILE);
  1224. X    while (fgets(act_rec, RECLEN-1, f) != NULL)
  1225. X    {
  1226. X        if (strtok (act_rec," \n") == NULL)
  1227. X            continue;
  1228. X        nread = strtok (NULL, " \n");
  1229. X        if (nread != NULL)
  1230. X            num = atoi(nread);
  1231. X        else
  1232. X            num = 0;
  1233. X        nread = strtok (NULL, " \n");
  1234. X        if (nread != NULL)
  1235. X            lownum = atoi(nread);
  1236. X        else
  1237. X            lownum = 0;
  1238. X        if (lownum > 0)
  1239. X            --lownum;
  1240. X        if (strlen(act_rec) > Max_name)
  1241. X            Max_name = strlen(act_rec);
  1242. X        hashenter (act_rec, num, lownum);
  1243. X    }
  1244. X
  1245. X    /* construct initial Newsorder */
  1246. X    entry_order();
  1247. X
  1248. X    fclose (f);
  1249. X}
  1250. X
  1251. X/*
  1252. X    check active newsgroups not mentioned in NEWSRC file
  1253. X    (FLG_SCAN not set)
  1254. X*/
  1255. Xstatic art_active ()
  1256. X{
  1257. X    char act_rec[RECLEN], *strtok();
  1258. X    NODE *ptr,*hashfind();
  1259. X    FILE *f,*fopen();
  1260. X    if ((f = fopen (ACTFILE,"r")) == NULL)
  1261. X        printex ("couldn't open %s\n",ACTFILE);
  1262. X    New_idx = Ncount;
  1263. X    while (fgets(act_rec, RECLEN-1, f) != NULL)
  1264. X    {
  1265. X        if (strtok (act_rec," \n") == NULL)
  1266. X            continue;
  1267. X        if ((ptr = hashfind (act_rec)) == NULL)
  1268. X            printex("%s - unexpected hash table failure",act_rec);
  1269. X        if ((ptr->state & FLG_SCAN) == 0)
  1270. X            chkgroup (ptr->nd_name, NEWS_ON, 0);
  1271. X    }
  1272. X}
  1273. X
  1274. X/*
  1275. X    check group for new articles:
  1276. X    s - group
  1277. X    c - subscription indicator from NEWSRC
  1278. X    n - number read
  1279. X*/
  1280. Xstatic chkgroup (s,c,n)
  1281. Xchar *s,c;
  1282. Xint n;
  1283. X{
  1284. X    NODE *ptr, *hashfind();
  1285. X    int lold,lowart;
  1286. X    lold = Lrec;
  1287. X    if ((ptr = hashfind(s)) != NULL && (ptr->state & FLG_SCAN) == 0)
  1288. X    {
  1289. X        Newsorder [Ncount] = ptr;
  1290. X        ++Ncount;
  1291. X        ptr->pages = 0;
  1292. X        ptr->state |= FLG_SCAN;
  1293. X        if (c == NEWS_ON)
  1294. X            ptr->state |= FLG_SUB;
  1295. X        /* if "read" more than exist reset to zero */
  1296. X        if (n > ptr->art)
  1297. X            n = 0;
  1298. X        lowart = ptr->rdnum;
  1299. X        if (n < ptr->rdnum)
  1300. X            n = ptr->rdnum;
  1301. X        ptr->orgrd = ptr->pgrd = ptr->rdnum = n;
  1302. X        ptr->pgshwn = 0L;
  1303. X
  1304. X        /*
  1305. X        ** scan decision is rather complex, since GF_ALL setting
  1306. X        ** overides "n" value, GF_SPEC indicates FLG_SPEC flag used.
  1307. X        ** if GF_OVER set, FLG_SPEC overides subscription mark, else
  1308. X        ** FLG_SPEC AND subscribed is neccesary.
  1309. X        */
  1310. X        if ((Gflags & GF_SPEC) != 0)
  1311. X        {
  1312. X            if ((ptr->state & FLG_SPEC) == 0)
  1313. X                c = NEWS_OFF;
  1314. X            else
  1315. X            {
  1316. X                if ((Gflags & GF_OVER) != 0)
  1317. X                    c = NEWS_ON;
  1318. X            }
  1319. X        }
  1320. X        if ((Gflags & GF_ALL) != 0)
  1321. X            n = lowart;
  1322. X        if (c == NEWS_ON && ptr->art > n)
  1323. X        {
  1324. X            outgroup (s,n,ptr->art);
  1325. X            if (lold != Lrec)
  1326. X            {
  1327. X                ptr->pnum = lold+1;
  1328. X                ptr->pages = Lrec - lold;
  1329. X                ptr->state |= FLG_PAGE;
  1330. X            }
  1331. X        }
  1332. X    }
  1333. X}
  1334. X
  1335. X/*
  1336. X    wr_newsrc writes the .newsrc file
  1337. X*/
  1338. Xwr_newsrc ()
  1339. X{
  1340. X    FILE *fp,*fopen();
  1341. X    NODE *p;
  1342. X    char c;
  1343. X    int i,rc;
  1344. X
  1345. X    if (link(Newsrc,Onews) < 0)
  1346. X        printex ("can't backup %s to %s before writing",Newsrc,Onews);
  1347. X
  1348. X    if (unlink(Newsrc) < 0 || (fp = fopen(Newsrc,"w")) == NULL)
  1349. X        printex ("can't open %s for writing (backed up in %s)",Newsrc,Onews);
  1350. X    else
  1351. X    {
  1352. X        clearerr(fp);
  1353. X        for (i=0; (rc = ferror(fp)) == 0 && i < Optlines; ++i)
  1354. X            fprintf (fp,"%s",Options[i]);
  1355. X        for (i=0; rc == 0 && i < Ncount; ++i)
  1356. X        {
  1357. X            p = Newsorder[i];
  1358. X            if ((p->state & FLG_SUB) == 0)
  1359. X                c = NEWS_OFF;
  1360. X            else
  1361. X                c = NEWS_ON;
  1362. X#ifdef OLDRC
  1363. X            fprintf (fp,"%s%c %d\n",p->nd_name,c,p->rdnum);
  1364. X#else
  1365. X            if (p->rdnum > 0)
  1366. X                fprintf (fp,"%s%c 1-%d\n",p->nd_name,c,p->rdnum);
  1367. X            else
  1368. X                fprintf (fp,"%s%c 0\n",p->nd_name,c);
  1369. X#endif
  1370. X            rc = ferror(fp);
  1371. X        }
  1372. X        fclose (fp);
  1373. X        if (rc != 0)
  1374. X            printex ("write of %s failed, old copy stored in %s",Newsrc,Onews);
  1375. X        else
  1376. X            unlink (Onews);
  1377. X    }
  1378. X}
  1379. X
  1380. Xnew_groups ()
  1381. X{
  1382. X    int i,wrem,w;
  1383. X    char fs[24],c_end;
  1384. X    if (New_idx >= Ncount || C_allow < (w = Max_name+1))
  1385. X        return (0);
  1386. X    term_set (ERASE);
  1387. X    printf (NEWGFORM,Newsrc);
  1388. X    sprintf (fs,"%%-%ds%%c",Max_name);
  1389. X    wrem = C_allow;
  1390. X    for (i=New_idx; i < Ncount; ++i)
  1391. X    {
  1392. X        if ((wrem -= w) < w)
  1393. X        {
  1394. X            wrem = C_allow;
  1395. X            c_end = '\n';
  1396. X        }
  1397. X        else
  1398. X            c_end = ' ';
  1399. X        printf (fs,(Newsorder[i])->nd_name,c_end);
  1400. X    }
  1401. X    if ((++wrem) < C_allow)
  1402. X        putchar ('\n');
  1403. X    return (i-New_idx);
  1404. X}
  1405. X
  1406. X/*
  1407. X    arg_opt must be called prior to option scanning, since
  1408. X    it uses the options array.  This is a bit of a kludge,
  1409. X    but it saves a bunch of work.  NOTE - no command name argument
  1410. X*/
  1411. Xstatic arg_opt (argc,argv)
  1412. Xint argc;
  1413. Xchar **argv;
  1414. X{
  1415. X    if (argc > OPTLINES)
  1416. X        printex ("too many command line options (%d allowed)\n",OPTLINES);
  1417. X    for (Optlines=0; Optlines < argc; ++Optlines)
  1418. X    {
  1419. X        Options[Optlines] = *argv;
  1420. X        ++argv;
  1421. X    }
  1422. X    newsrc_opt();
  1423. X}
  1424. X
  1425. X/*
  1426. X    option setting routine:
  1427. X    sets global flags: GF_ALL for -x option GF_SPEC for -n.
  1428. X    sets up filter array for article scanning
  1429. X*/
  1430. Xstatic newsrc_opt()
  1431. X{
  1432. X    int i;
  1433. X    char curopt,tmp[RECLEN],*tok,*strtok(),*index();
  1434. X
  1435. X    Nounsub = Listfirst = 0;
  1436. X    Ntopt = Nwopt = Nnwopt = Nntopt = 0;
  1437. X    curopt = '\0';
  1438. X    for (i=0; i < Optlines; ++i)
  1439. X    {
  1440. X        strcpy(tmp,Options[i]);
  1441. X        for (tok = strtok(tmp,",\\ \t\n"); tok != NULL; tok = strtok(NULL,",\\ \t\n"))
  1442. X        {
  1443. X            if (*tok != '-')
  1444. X                do_opt (curopt,tok);
  1445. X            else
  1446. X            {
  1447. X                for (++tok; index("nwt",*tok) == NULL; ++tok)
  1448. X                {
  1449. X                    /* options with no strings */
  1450. X                    switch(*tok)
  1451. X                    {
  1452. X                    case 'S':
  1453. X                        Gflags &= ~GF_OVER;
  1454. X                        break;
  1455. X                    case '%':
  1456. X                        Listfirst = 1;
  1457. X                        break;
  1458. X                    case 'U':
  1459. X                        Nounsub = 1;
  1460. X                        break;
  1461. X#ifdef OLDRC
  1462. X                    case 'i':
  1463. X                    /* Treat "-i" as synonym for "-x" */
  1464. X#endif
  1465. X                    case 'x':
  1466. X                        Gflags |= GF_ALL;
  1467. X                    default:
  1468. X                        break;
  1469. X                    }
  1470. X                }
  1471. X                curopt = *tok;
  1472. X                if (*(++tok) != '\0')
  1473. X                    do_opt (curopt,tok);
  1474. X            }
  1475. X        }
  1476. X    }
  1477. X}
  1478. X
  1479. X/* do_opt is for options with strings attached */
  1480. Xstatic do_opt (opt,str)
  1481. Xchar opt, *str;
  1482. X{
  1483. X    switch (opt)
  1484. X    {
  1485. X    case 'n':
  1486. X        Gflags |= GF_SPEC;
  1487. X        specmark(str);
  1488. X        break;
  1489. X    case 'w':
  1490. X        specfilter (FIL_AUTHOR,str);
  1491. X        break;
  1492. X    case 't':
  1493. X        specfilter (FIL_TITLE,str);
  1494. X        break;
  1495. X    default:
  1496. X#ifdef OLDRC
  1497. X        Gflags |= GF_SPEC;    /* Assume anything else is newsgroup */
  1498. X        specmark(str);
  1499. X#endif
  1500. X        break;
  1501. X    }
  1502. X}
  1503. X
  1504. Xstatic specfilter (comp,str)
  1505. Xchar comp,*str;
  1506. X{
  1507. X    char *regcmp();
  1508. X    int *count;
  1509. X    char **rex;
  1510. X
  1511. X    /*
  1512. X    ** we may set rex one past end of array.  we will error before
  1513. X    ** referencing it if that's the case, however.
  1514. X    */
  1515. X    if (*str == '!')
  1516. X    {
  1517. X        if (comp == FIL_TITLE)
  1518. X        {
  1519. X            count = &Nntopt;
  1520. X            rex = Negtopt + *count;
  1521. X        }
  1522. X        else
  1523. X        {
  1524. X            count = &Nnwopt;
  1525. X            rex = Negwopt + *count;
  1526. X        }
  1527. X        ++str;
  1528. X    }
  1529. X    else
  1530. X    {
  1531. X        if (comp == FIL_TITLE)
  1532. X        {
  1533. X            count = &Ntopt;
  1534. X            rex = Topt + *count;
  1535. X        }
  1536. X        else
  1537. X        {
  1538. X            count = &Nwopt;
  1539. X            rex = Wopt + *count;
  1540. X        }
  1541. X    }
  1542. X    if (*count >= NUMFILTER)
  1543. X        printex ("too many %c options, %d allowed",comp,NUMFILTER);
  1544. X    if ((*rex = regcmp(str,(char *) 0)) == NULL)
  1545. X        printex ("%c option regular expression syntax: %s",comp,str);
  1546. X    ++(*count);
  1547. X}
  1548. X
  1549. X/*
  1550. X    handle the newsgroup specification string.
  1551. X    ("all" convention - braack!!!)
  1552. X*/
  1553. Xstatic specmark (s)
  1554. Xchar *s;
  1555. X{
  1556. X    unsigned ormask,andmask;
  1557. X    int i,len;
  1558. X    char *ptr,*re,pattern[RECLEN],*regex(),*regcmp();
  1559. X
  1560. X    if (*s == '!')
  1561. X    {
  1562. X        ++s;
  1563. X        ormask = 0;
  1564. X        andmask = ~FLG_SPEC;
  1565. X        if (*s == '\0')
  1566. X            return;
  1567. X    }
  1568. X    else
  1569. X    {
  1570. X        ormask = FLG_SPEC;
  1571. X        andmask = 0xffff;
  1572. X    }
  1573. X
  1574. X    /* convert "all" not bounded by alphanumerics to ".*". ".all" becomes ".*" */
  1575. X    for (ptr = s; (len = findall(ptr)) >= 0; ptr += len+1)
  1576. X    {
  1577. X        if (len > 0 && isalnum (s[len-1]))
  1578. X            continue;
  1579. X        if (isalnum (s[len+3]))
  1580. X            continue;
  1581. X        if (len > 0 && s[len-1] == '.')
  1582. X        {
  1583. X            --len;
  1584. X            strcpy (s+len,s+len+1);
  1585. X        }
  1586. X        s[len] = '.';
  1587. X        s[len+1] = '*';
  1588. X        strcpy (s+len+2,s+len+3);
  1589. X    }
  1590. X
  1591. X    /* now use regular expressions */
  1592. X    sprintf (pattern,"^%s$",s);
  1593. X    if ((re = regcmp(pattern,(char *) 0)) == NULL)
  1594. X        printex ("n option regular expression syntax: %s",s);
  1595. X    for (i=0; i < Ncount; ++i)
  1596. X    {
  1597. X        if (regex(re,(Newsorder[i])->nd_name) != NULL)
  1598. X        {
  1599. X            (Newsorder[i])->state |= ormask;
  1600. X            (Newsorder[i])->state &= andmask;
  1601. X        }
  1602. X    }
  1603. X    regfree (re);
  1604. X}
  1605. X
  1606. Xstatic findall (s)
  1607. Xchar *s;
  1608. X{
  1609. X    int len;
  1610. X    for (len=0; *s != '\0'; ++s,++len)
  1611. X    {
  1612. X        if (*s == 'a' && strncmp(s,"all",3) == 0)
  1613. X            return (len);
  1614. X    }
  1615. X    return (-1);
  1616. X}
  1617. @//E*O*F newsrc.c//
  1618. if test 11576 -ne "`wc -c <'newsrc.c'`"; then
  1619.     echo shar: error transmitting "'newsrc.c'" '(should have been 11576 characters)'
  1620. fi
  1621. fi # end of overwriting check
  1622. echo shar: extracting "'pagefile.c'" '(5053 characters)'
  1623. if test -f 'pagefile.c' ; then 
  1624.   echo shar: will not over-write existing file "'pagefile.c'"
  1625. else
  1626. sed 's/^X//' >pagefile.c <<'@//E*O*F pagefile.c//'
  1627. X/*
  1628. X** vn news reader.
  1629. X**
  1630. X** pagefile.c - routines to deal with page display tempfile
  1631. X**
  1632. X** see copyright disclaimer / history in vn.c source file
  1633. X*/
  1634. X
  1635. X#include <stdio.h>
  1636. X
  1637. X#ifdef SYSV
  1638. X#include <sys/types.h>
  1639. X#include <fcntl.h>
  1640. X#endif
  1641. X
  1642. X#include <sys/file.h>
  1643. X#include "vn.h"
  1644. X#include "head.h"
  1645. X
  1646. Xextern int Ncount,Lrec,L_allow,Cur_page,C_allow;
  1647. Xextern int Nwopt, Nnwopt, Ntopt, Nntopt;
  1648. Xextern char *Wopt[], *Topt[], *Negtopt[], *Negwopt[];
  1649. Xextern NODE **Newsorder;
  1650. Xextern PAGE Page;
  1651. Xextern int Digest;
  1652. X
  1653. Xextern char *Aformat;
  1654. X
  1655. Xextern char *T_head, *F_head, *L_head;
  1656. X
  1657. Xstatic int Tdes;    /* temp file descriptor */
  1658. Xstatic int Pgsize;    /* block size for seeking file */
  1659. X
  1660. X/*
  1661. X    routines which deal with the temp file containing
  1662. X    display pages.  Note the "invisible" file feature -
  1663. X    tempfile is unlinked from /usr/tmp immediately.  when
  1664. X    Tdes is closed by UNIX the disk space will be given back.
  1665. X*/
  1666. X
  1667. Xtemp_open ()
  1668. X{
  1669. X    char tmpart [L_tmpnam];
  1670. X    Lrec = -1;
  1671. X    tmpnam (tmpart);
  1672. X    Pgsize = sizeof (HEAD) + L_allow * sizeof(BODY);
  1673. X    if ((Tdes = open(tmpart,O_RDWR|O_CREAT)) < 0)
  1674. X        printex ("can't open %s",tmpart);
  1675. X    unlink (tmpart);
  1676. X}
  1677. X
  1678. X/*
  1679. X    create page records for newsgroup s
  1680. X    all articles between low and hi are to be included.
  1681. X*/
  1682. Xoutgroup (s,low,hi)
  1683. Xchar *s;
  1684. Xint low,hi;
  1685. X{
  1686. X    int i,aid;
  1687. X    char title[RECLEN],gd[RECLEN];
  1688. X    g_dir(s,gd);
  1689. X    if (chdir(gd) < 0)
  1690. X    {
  1691. X        grp_indic(s,0);
  1692. X        return;
  1693. X    }
  1694. X    grp_indic(s,1);
  1695. X    aid = 0;
  1696. X    for (i=low+1; i <= hi; ++i)
  1697. X    {
  1698. X        if (digname (i,title) >= 0)
  1699. X        {
  1700. X            Page.b[aid].art_id = i;
  1701. X            Page.b[aid].art_mark = ' ';
  1702. X            strcpy (Page.b[aid].art_t, title);
  1703. X            if ((++aid) >= L_allow)
  1704. X            {
  1705. X
  1706. X                /* start next page */
  1707. X                Page.h.artnum = L_allow;
  1708. X                do_write ();
  1709. X                ++Lrec;
  1710. X                aid = 0;
  1711. X            }
  1712. X        }
  1713. X    }
  1714. X
  1715. X    /* last page (partial) */
  1716. X    if (aid != 0)
  1717. X    {
  1718. X        Page.h.artnum = aid;
  1719. X        do_write ();
  1720. X        ++Lrec;
  1721. X    }
  1722. X}
  1723. X
  1724. X/*
  1725. X    set current page to n.  use Pgsize and lseek to find it in
  1726. X    temp file (descriptor Tdes).
  1727. X*/
  1728. Xfind_page (n)
  1729. Xint n;
  1730. X{
  1731. X    long off,lseek();
  1732. X    int i,last;
  1733. X    Cur_page = n;
  1734. X    off = Pgsize;
  1735. X    off *= (long) n;
  1736. X    lseek (Tdes, off, 0);
  1737. X    if (read(Tdes, (char *) &(Page.h), sizeof(HEAD)) < sizeof(HEAD))
  1738. X        printex("bad temp file read");
  1739. X    i = Pgsize - sizeof(HEAD);
  1740. X    if (read(Tdes, (char *) Page.b, i) < i)
  1741. X        printex("bad temp file read");
  1742. X    last = -1;
  1743. X    for (i=0; i < Ncount; ++i)
  1744. X    {
  1745. X        if ((Newsorder[i])->pages > 0)
  1746. X        {
  1747. X            if ((Newsorder[i])->pnum > n)
  1748. X                break;
  1749. X            last = i;
  1750. X        }
  1751. X    }
  1752. X    if (last < 0)
  1753. X        printex ("can't find page %d",n);
  1754. X    Page.h.group = Newsorder[last];
  1755. X    Page.h.name = (Page.h.group)->nd_name;
  1756. X    cd_group ();
  1757. X}
  1758. X
  1759. Xwrite_page ()
  1760. X{
  1761. X    long off,lseek();
  1762. X    if (!Digest)
  1763. X    {
  1764. X        off = Pgsize;
  1765. X        off *= (long) Cur_page;
  1766. X        lseek (Tdes, off, 0);
  1767. X        do_write();
  1768. X    }
  1769. X}
  1770. X
  1771. Xstatic do_write()
  1772. X{
  1773. X    int num;
  1774. X
  1775. X    if (write(Tdes, (char *) &(Page.h), sizeof(HEAD)) < sizeof(HEAD))
  1776. X        printex ("Bad temp file write");
  1777. X    num = L_allow * sizeof(BODY);
  1778. X    if (write(Tdes, (char *) Page.b, num) < num)
  1779. X        printex ("Bad temp file write");
  1780. X}
  1781. X
  1782. X/*
  1783. X    find article title:
  1784. X    n - articles id
  1785. X    t - returned title - must have storage for RECLEN, assumed to be
  1786. X        > 3 * max title length also.
  1787. X*/
  1788. Xstatic digname (n, t)
  1789. Xint n;
  1790. Xchar *t;
  1791. X{
  1792. X    int i,j;
  1793. X    FILE *fp,*fopen();
  1794. X    char ff [MAX_C+1],fn [MAX_C+1],fl [MAX_C+1],*index();
  1795. X
  1796. X    /* open article */
  1797. X    sprintf (t,"%d", n);
  1798. X    if ((fp = fopen(t,"r")) == NULL)
  1799. X        return (-1);
  1800. X
  1801. X    /* get subject, from and lines by reading article */
  1802. X    ff[0] = fn[0] = fl[0] = '?';
  1803. X    ff[1] = fn[1] = fl[1] = '\0';
  1804. X    ff[C_allow] = fn[C_allow] = fl[C_allow] = '\0';
  1805. X    for (i = 0; i < HDR_LINES && fgets(t,RECLEN-1,fp) != NULL; ++i)
  1806. X    {
  1807. X        if (index(CHFIRST,t[0]) == NULL)
  1808. X            continue;
  1809. X        t[strlen(t) - 1] = '\0';
  1810. X        if (strncmp(T_head,t,THDLEN) == 0)
  1811. X        {
  1812. X            for (j=0; j < Nntopt; ++j)
  1813. X            {
  1814. X                if (regex(Negtopt[j],t+THDLEN) != NULL)
  1815. X                {
  1816. X                    fclose(fp);
  1817. X                    return(-1);
  1818. X                }
  1819. X            }
  1820. X            if (Ntopt > 0)
  1821. X            {
  1822. X                for (j=0; j < Ntopt; ++j)
  1823. X                {
  1824. X                    if (regex(Topt[j],t+THDLEN) != NULL)
  1825. X                        break;
  1826. X                }
  1827. X                if (j >= Ntopt)
  1828. X                {
  1829. X                    fclose(fp);
  1830. X                    return(-1);
  1831. X                }
  1832. X            }
  1833. X            strncpy(fn,t+THDLEN,C_allow);
  1834. X            continue;
  1835. X        }
  1836. X        if (strncmp(F_head,t,FHDLEN) == 0)
  1837. X        {
  1838. X            for (j=0; j < Nnwopt; ++j)
  1839. X            {
  1840. X                if (regex(Negwopt[j],t+FHDLEN) != NULL)
  1841. X                {
  1842. X                    fclose(fp);
  1843. X                    return(-1);
  1844. X                }
  1845. X            }
  1846. X            if (Nwopt > 0)
  1847. X            {
  1848. X                for (j=0; j < Nwopt; ++j)
  1849. X                {
  1850. X                    if (regex(Wopt[j],t+FHDLEN) != NULL)
  1851. X                        break;
  1852. X                }
  1853. X                if (j >= Nwopt)
  1854. X                {
  1855. X                    fclose(fp);
  1856. X                    return(-1);
  1857. X                }
  1858. X            }
  1859. X            strncpy(ff,t+FHDLEN,C_allow);
  1860. X            continue;
  1861. X        }
  1862. X        if (strncmp(L_head,t,LHDLEN) == 0)
  1863. X        {
  1864. X            strncpy(fl,t+LHDLEN,C_allow);
  1865. X            break;
  1866. X        }
  1867. X    }
  1868. X
  1869. X    fclose (fp);
  1870. X
  1871. X    /* reject empty or 1 line files */
  1872. X    if (i < 2)
  1873. X        return (-1);
  1874. X
  1875. X    form_title (t,fn,fl,ff,n);
  1876. X    return (0);
  1877. X}
  1878. X
  1879. Xform_title (t,fn,fl,ff,n)
  1880. Xchar *t,*fn,*fl,*ff;
  1881. Xint n;
  1882. X{
  1883. X    char *ptr,*index();
  1884. X    int i;
  1885. X
  1886. X    if ((ptr = index(ff,'(')) != NULL && strlen(ptr) > 3)
  1887. X        ff = ptr;
  1888. X    sprintf (t,TFORMAT,fn,fl,ff);
  1889. X    sprintf(ff,Aformat,' ',' ',n);
  1890. X    i = C_allow - strlen(ff) + 1;    /* remember newline in Aformat */
  1891. X    t[i] = '\0';
  1892. X    ctl_xlt(t);
  1893. X    return (0);
  1894. X}
  1895. X
  1896. X/* replace control characters in titles */
  1897. Xstatic ctl_xlt(s)
  1898. Xchar *s;
  1899. X{
  1900. X    while (*s != '\0')
  1901. X    {
  1902. X        if (*s < ' ')
  1903. X            *s += 'A' - 1;
  1904. X        ++s;
  1905. X    }
  1906. X}
  1907. @//E*O*F pagefile.c//
  1908. if test 5053 -ne "`wc -c <'pagefile.c'`"; then
  1909.     echo shar: error transmitting "'pagefile.c'" '(should have been 5053 characters)'
  1910. fi
  1911. fi # end of overwriting check
  1912. echo shar: extracting "'reader.h'" '(1498 characters)'
  1913. if test -f 'reader.h' ; then 
  1914.   echo shar: will not over-write existing file "'reader.h'"
  1915. else
  1916. sed 's/^X//' >reader.h <<'@//E*O*F reader.h//'
  1917. X/*
  1918. X** vn news reader.
  1919. X**
  1920. X** reader.h - article reading interface definitions
  1921. X**
  1922. X** see copyright disclaimer / history in vn.c source file
  1923. X*/
  1924. X
  1925. X#define PAGE_MID ":more (%2d%%):"
  1926. X#define PAGE_NEXT ":next article:"
  1927. X#define PAGE_END ":end:"
  1928. X#define PAGE_NO ":?:"
  1929. X#define PPR_MAX 18    /* maximum length of PAGE prompts */
  1930. X
  1931. X/*
  1932. X    reading commands: no control chars, add help message to helppg
  1933. X    SAVE, PRINT, HEADTOG and SETROT are also recognized
  1934. X*/
  1935. X#define HPG_HEAD "toggle header print flag"
  1936. X#define HPG_ROT "toggle rotation"
  1937. X#define HPG_SAVE "save article in a file"
  1938. X#define HPG_PRINT "print article"
  1939. X#define PG_NEXT 'n'
  1940. X#define HPG_NEXT "next article, if any"
  1941. X#define PG_QUIT 'q'
  1942. X#define HPG_QUIT "quit reading articles, if any more to read"
  1943. X#define PG_FLIP 'Q'
  1944. X#define HPG_FLIP "quit reading, and turn to next page of articles"
  1945. X#define PG_FOLLOW 'f'
  1946. X#define HPG_FOLLOW "post followup to article"
  1947. X#define PG_REPLY 'm'
  1948. X#define HPG_REPLY "send mail to author of article"
  1949. X#define PG_HELP '?'
  1950. X#define HPG_HELP "see this help menu"
  1951. X#define PG_REWIND 'r'
  1952. X#define HPG_REWIND "rewind article to beginning"
  1953. X#define PG_WIND 'e'
  1954. X#define HPG_WIND "seek to end of article (to next/end prompt)"
  1955. X#define PG_STEP '\n'
  1956. X#define HPG_STEP "next line"
  1957. X#define PG_SEARCH '/'
  1958. X#define HPG_SEARCH "search for regular expression in remainder of article"
  1959. X#define SEARCHFORM "search pattern (%s) ? "
  1960. X#define HPG_DEF "\n anything else to continue normal reading"
  1961. X#define HPG_EDEF "\n anything else to try reading next article, if any"
  1962. @//E*O*F reader.h//
  1963. if test 1498 -ne "`wc -c <'reader.h'`"; then
  1964.     echo shar: error transmitting "'reader.h'" '(should have been 1498 characters)'
  1965. fi
  1966. fi # end of overwriting check
  1967. echo shar: extracting "'reg.c'" '(1656 characters)'
  1968. if test -f 'reg.c' ; then 
  1969.   echo shar: will not over-write existing file "'reg.c'"
  1970. else
  1971. sed 's/^X//' >reg.c <<'@//E*O*F reg.c//'
  1972. X/*
  1973. X** vn news reader.
  1974. X**
  1975. X** reg.c - implementation of regex / regcmp on top of UCB library
  1976. X**
  1977. X** see copyright disclaimer / history in vn.c source file
  1978. X*/
  1979. X
  1980. X#include <stdio.h>
  1981. X
  1982. X#define RGBLKSIZE 20
  1983. X
  1984. Xstruct _regtab
  1985. X{
  1986. X    struct _regtab *link;
  1987. X    char *regstr;
  1988. X};
  1989. X
  1990. Xtypedef struct _regtab REGTAB;
  1991. X
  1992. Xstatic REGTAB *Chain = NULL;
  1993. Xstatic REGTAB *Free = NULL;
  1994. Xstatic REGTAB *Compiled = NULL;
  1995. X
  1996. Xregfree(s)
  1997. Xchar *s;
  1998. X{
  1999. X    REGTAB *ptr,*cmp,*old;
  2000. X
  2001. X    cmp = (REGTAB *) s;
  2002. X    old = NULL;
  2003. X
  2004. X    for (ptr = Chain; ptr != NULL; ptr = (old = ptr)->link)
  2005. X    {
  2006. X        if (ptr == cmp)
  2007. X        {
  2008. X            if (old == NULL)
  2009. X                Chain = Chain->link;
  2010. X            else
  2011. X                old->link = ptr->link;
  2012. X            ptr->link = Free;
  2013. X            Free = ptr;
  2014. X            break;
  2015. X        }
  2016. X    }
  2017. X}
  2018. X
  2019. Xchar *regcmp(str)
  2020. Xchar *str;
  2021. X{
  2022. X    int i;
  2023. X    char *str_store();
  2024. X    char *re_comp();
  2025. X
  2026. X    if (re_comp(str) != NULL)
  2027. X    {
  2028. X        Compiled = NULL;    /* make sure we're OK */
  2029. X        return(NULL);
  2030. X    }
  2031. X
  2032. X    if (Free == NULL)
  2033. X    {
  2034. X        Free = (REGTAB *) malloc(RGBLKSIZE * sizeof(REGTAB));
  2035. X        if (Free == NULL)
  2036. X            printex ("regcmp: memory allocation failure");
  2037. X        for (i = 0; i < RGBLKSIZE - 1; ++i)
  2038. X            Free[i].link = Free + i + 1;
  2039. X        Free[i].link = NULL;
  2040. X    }
  2041. X
  2042. X    Compiled = Free;
  2043. X    Free = Free->link;
  2044. X
  2045. X    Compiled->link = Chain;
  2046. X    Chain = Compiled;
  2047. X    Compiled->regstr = str_store(str);
  2048. X
  2049. X    return ((char *) Compiled);
  2050. X}
  2051. X
  2052. Xchar *regex(reg,str)
  2053. Xchar *reg,*str;
  2054. X{
  2055. X    REGTAB *cmp;
  2056. X
  2057. X    cmp = (REGTAB *) reg;
  2058. X
  2059. X    if (cmp == Compiled)
  2060. X    {
  2061. X        if (re_exec(str))
  2062. X            return(str);
  2063. X        return (NULL);
  2064. X    }
  2065. X
  2066. X    for (Compiled = Chain; Compiled != NULL; Compiled = Compiled->link)
  2067. X    {
  2068. X        if (Compiled == cmp)
  2069. X            break;
  2070. X    }
  2071. X
  2072. X    if (Compiled == NULL)
  2073. X        printex ("regex: bad pointer");
  2074. X
  2075. X    re_comp(Compiled->regstr);
  2076. X
  2077. X    if (re_exec(str))
  2078. X        return(str);
  2079. X
  2080. X    return(NULL);
  2081. X}
  2082. @//E*O*F reg.c//
  2083. if test 1656 -ne "`wc -c <'reg.c'`"; then
  2084.     echo shar: error transmitting "'reg.c'" '(should have been 1656 characters)'
  2085. fi
  2086. fi # end of overwriting check
  2087. echo shar: extracting "'sig_set.c'" '(4501 characters)'
  2088. if test -f 'sig_set.c' ; then 
  2089.   echo shar: will not over-write existing file "'sig_set.c'"
  2090. else
  2091. sed 's/^X//' >sig_set.c <<'@//E*O*F sig_set.c//'
  2092. X/*
  2093. X** vn news reader.
  2094. X**
  2095. X** sig_set.c - signal handler
  2096. X**
  2097. X** see copyright disclaimer / history in vn.c source file
  2098. X*/
  2099. X
  2100. X#include <stdio.h>
  2101. X#include <sys/signal.h>
  2102. X#include <sgtty.h>
  2103. X#include <setjmp.h>
  2104. X#include "tty.h"
  2105. X#include "vn.h"
  2106. X#include "config.h"
  2107. X
  2108. Xextern int L_allow;
  2109. Xextern char *Version;
  2110. X
  2111. Xstatic int Sigflag=BRK_INIT;    /* phase of interaction */
  2112. Xstatic FILE **Fpseek;        /* article reading file pointer pointer */
  2113. Xstatic int Foreground;
  2114. Xstatic jmp_buf Jumploc;        /* for BRK_SESS phase */
  2115. Xstatic char *Cur_scn;        /* current group name being scanned */
  2116. X
  2117. X/*
  2118. X    interrupt handler - unusual termination (longjmp and printex aborts)
  2119. X    if not abort, remember to reset signal trap
  2120. X    CAUTION - the passing of a jump buffer is a little dicey - assumes
  2121. X    type jump_buf is an array.
  2122. X
  2123. X    sigcatch and sig_set control a lot of i/o on stderr also, since
  2124. X    it is so intimately related to signal interaction.  Note that the
  2125. X    SIGTSTP action causes a "stopped on tty output" if raw terminal
  2126. X    mode is restored by tty_set(RESTORE).  We don't get it if we were
  2127. X    already cooked since tty_set avoids calling ioctl if it doesn't
  2128. X    have to.
  2129. X*/
  2130. Xstatic sigcatch (sig)
  2131. Xint sig;
  2132. X{
  2133. X    char buf [MAX_C+1];
  2134. X    int pgrp;
  2135. X
  2136. X    /* disable signal while processing it */
  2137. X    signal (sig,SIG_IGN);
  2138. X
  2139. X    switch (sig)
  2140. X    {
  2141. X    case SIGINT:
  2142. X    case SIGQUIT:
  2143. X        break;
  2144. X
  2145. X#ifdef JOBCONTROL
  2146. X    case SIGTSTP:
  2147. X        /* ignore SIGTTOU so we don't get stopped if [kc]sh grabs the tty */
  2148. X        signal(SIGTTOU, SIG_IGN);
  2149. X        tty_set (SAVEMODE);
  2150. X        term_set (MOVE,0,L_allow+RECBIAS-1);
  2151. X        printf ("\n");
  2152. X        Foreground = 0;
  2153. X        fflush (stdout);
  2154. X        fflush (stderr);
  2155. X        signal(SIGTTOU, SIG_DFL);
  2156. X
  2157. X        /* Send the TSTP signal to suspend our process group */
  2158. X        signal(SIGTSTP, SIG_DFL);
  2159. X        sigsetmask(0);
  2160. X        kill (0, SIGTSTP);
  2161. X
  2162. X        /* WE ARE NOW STOPPED */
  2163. X
  2164. X        /*
  2165. X                WELCOME BACK!
  2166. X                if terminals process group is ours, we are foregrounded again
  2167. X                and can turn newsgroup name printing back on
  2168. X            */
  2169. X        tty_set (RESTORE);
  2170. X        switch (Sigflag)
  2171. X        {
  2172. X        case BRK_SESS:
  2173. X            signal (SIGTSTP,sigcatch);
  2174. X            longjmp (Jumploc,1);
  2175. X        case BRK_IN:
  2176. X            ioctl (1,TIOCGPGRP,&pgrp);
  2177. X            if (pgrp == getpgrp(0))
  2178. X            {
  2179. X                Foreground = 1;
  2180. X                if (Cur_scn != NULL)
  2181. X                    fgprintf ("    %s\n",Cur_scn);
  2182. X            }
  2183. X            break;
  2184. X        default:
  2185. X            break;
  2186. X        }
  2187. X        signal (SIGTSTP,sigcatch);
  2188. X        return;
  2189. X#endif
  2190. X    default:
  2191. X        printex (BRK_MSG,sig);
  2192. X    }
  2193. X
  2194. X    /* QUIT and INTERRUPT signals */
  2195. X    switch (Sigflag)
  2196. X    {
  2197. X    case BRK_SESS:
  2198. X        /* if in session, ask if really a quit, do longjump if not */
  2199. X        term_set (ERASE);
  2200. X        tty_set (RAWMODE);
  2201. X        user_str (buf, BRK_PR, 1);
  2202. X        if (buf[0] == 'y')
  2203. X            printex (BRK_MSG,sig);
  2204. X        signal (sig,sigcatch);
  2205. X        longjmp (Jumploc,1);
  2206. X    case BRK_READ:
  2207. X        /* if reading seek file to end to abort page printing */
  2208. X        printf ("\n");
  2209. X        if (*Fpseek == NULL || fseek(*Fpseek,0L,2) < 0)
  2210. X            putchar ('\07');
  2211. X        break;
  2212. X    default:
  2213. X        printex (BRK_MSG,sig);
  2214. X    }
  2215. X    signal (sig,sigcatch);
  2216. X}
  2217. X
  2218. X/*
  2219. X    sig_set controls what will be done with a signal when picked up by
  2220. X    sigcatch.  grp_indic / fgprintf is included here to keep knowledge
  2221. X    of TSTP state localized.
  2222. X*/
  2223. X/* VARARGS */
  2224. Xsig_set (flag,dat)
  2225. Xint flag, *dat;
  2226. X{
  2227. X    int i, *xfer, pgrp;
  2228. X    if (Sigflag == BRK_INIT)
  2229. X    {
  2230. X        Cur_scn = NULL;
  2231. X        signal (SIGINT,sigcatch);
  2232. X        signal (SIGQUIT,sigcatch);
  2233. X        signal (SIGHUP,sigcatch);
  2234. X        signal (SIGTERM,sigcatch);
  2235. X#ifdef JOBCONTROL
  2236. X        signal (SIGTSTP,sigcatch);
  2237. X        ioctl (1,TIOCGPGRP,&pgrp);
  2238. X        if (pgrp == getpgrp(0))
  2239. X        {
  2240. X            Foreground = 1;
  2241. X            fgprintf ("Visual News, Release %s, reading:\n",Version);
  2242. X        }
  2243. X        else
  2244. X            Foreground = 0;
  2245. X#else
  2246. X        Foreground = NOJOB_FG;
  2247. X#endif
  2248. X    }
  2249. X    switch (flag)
  2250. X    {
  2251. X    case BRK_IN:
  2252. X    case BRK_OUT:
  2253. X        Sigflag = flag;
  2254. X        break;
  2255. X    case BRK_READ:
  2256. X        if (Sigflag != BRK_SESS)
  2257. X            printex ("unexpected read state, sig_set\n");
  2258. X        Fpseek = (FILE **) dat;
  2259. X        Sigflag = BRK_READ;
  2260. X        break;
  2261. X    case BRK_SESS:
  2262. X        xfer = (int *) Jumploc;
  2263. X        for (i=0; i < sizeof(Jumploc) / sizeof(int); ++i)
  2264. X            xfer[i] = dat[i];
  2265. X        Sigflag = BRK_SESS;
  2266. X        break;
  2267. X    case BRK_RFIN:
  2268. X        if (Sigflag != BRK_READ)
  2269. X            printex ("unexpected finish state, sig_set\n");
  2270. X        Sigflag = BRK_SESS;
  2271. X        break;
  2272. X    default:
  2273. X        printex ("bad state %d, sig_set\n",flag);
  2274. X    }
  2275. X}
  2276. X
  2277. Xgrp_indic (s,ok)
  2278. Xchar *s;
  2279. Xint ok;
  2280. X{
  2281. X    NODE *ptr,*hashfind();
  2282. X
  2283. X    /* we go to hash table because s might be a temporary buffer */
  2284. X    if ((ptr = hashfind(s)) != NULL)
  2285. X    {
  2286. X        Cur_scn = ptr->nd_name;
  2287. X        if (Foreground)
  2288. X        {
  2289. X            if (ok)
  2290. X                fgprintf("    %s\n",Cur_scn);
  2291. X            else
  2292. X                fgprintf("    %s - Can't access spool directory\n",Cur_scn);
  2293. X        }
  2294. X    }
  2295. X}
  2296. X
  2297. Xfgprintf (fs,a,b,c,d,e)
  2298. Xchar *fs;
  2299. Xint a,b,c,d,e;
  2300. X{
  2301. X    if (Foreground)
  2302. X        fprintf (stderr,fs,a,b,c,d,e);
  2303. X    fflush (stderr);
  2304. X}
  2305. @//E*O*F sig_set.c//
  2306. if test 4501 -ne "`wc -c <'sig_set.c'`"; then
  2307.     echo shar: error transmitting "'sig_set.c'" '(should have been 4501 characters)'
  2308. fi
  2309. fi # end of overwriting check
  2310. echo shar: extracting "'storage.c'" '(1309 characters)'
  2311. if test -f 'storage.c' ; then 
  2312.   echo shar: will not over-write existing file "'storage.c'"
  2313. else
  2314. sed 's/^X//' >storage.c <<'@//E*O*F storage.c//'
  2315. X/*
  2316. X** vn news reader.
  2317. X**
  2318. X** storage.c - storage allocation routines
  2319. X**
  2320. X** see copyright disclaimer / history in vn.c source file
  2321. X*/
  2322. X
  2323. X#include <stdio.h>
  2324. X#include "vn.h"
  2325. X
  2326. Xextern char *malloc();
  2327. X
  2328. Xextern int L_allow;
  2329. X
  2330. Xextern PAGE Page;
  2331. X/*
  2332. X    Storage allocaters.  One more call to malloc in entry_order routine.
  2333. X*/
  2334. X
  2335. Xchar *str_store (s)
  2336. Xchar *s;
  2337. X{
  2338. X    static unsigned av_len = 0;    /* current storage available */
  2339. X    static char *avail;
  2340. X    int len;
  2341. X
  2342. X    if (s == NULL)
  2343. X        s = "";
  2344. X
  2345. X    if ((len = strlen(s)+1) > av_len)
  2346. X    {
  2347. X        if (len > STRBLKSIZE)
  2348. X            av_len = len;
  2349. X        else
  2350. X            av_len = STRBLKSIZE;
  2351. X        if ((avail = malloc(av_len)) == NULL)
  2352. X            printex ("can't allocate memory for string storage");
  2353. X    }
  2354. X    strcpy (avail,s);
  2355. X    s = avail;
  2356. X    avail += len;
  2357. X    av_len -= len;
  2358. X    return (s);
  2359. X}
  2360. X
  2361. X/*
  2362. X** called after number of terminal lines (L_allow) is known, to set
  2363. X** up storage for Page.
  2364. X*/
  2365. Xpage_alloc ()
  2366. X{
  2367. X    char *body;
  2368. X
  2369. X    if ((body = malloc(L_allow*sizeof(BODY))) == NULL)
  2370. X        printex ("can't allocate memory for display storage");
  2371. X
  2372. X    Page.b = (BODY *) body;
  2373. X}
  2374. X
  2375. XNODE
  2376. X*node_store()
  2377. X{
  2378. X    static int nd_avail = 0;
  2379. X    static NODE *nd;
  2380. X    NODE *ret;
  2381. X
  2382. X    if (nd_avail <= 0)
  2383. X    {
  2384. X        if ((nd = (NODE *) malloc(sizeof(NODE)*NDBLKSIZE)) == NULL)
  2385. X            printex ("can't allocate memory for newsgroup table");
  2386. X        nd_avail = NDBLKSIZE;
  2387. X    }
  2388. X    --nd_avail;
  2389. X    ret = nd;
  2390. X    ++nd;
  2391. X    return(ret);
  2392. X}
  2393. @//E*O*F storage.c//
  2394. if test 1309 -ne "`wc -c <'storage.c'`"; then
  2395.     echo shar: error transmitting "'storage.c'" '(should have been 1309 characters)'
  2396. fi
  2397. fi # end of overwriting check
  2398. echo shar: extracting "'strings.c'" '(720 characters)'
  2399. if test -f 'strings.c' ; then 
  2400.   echo shar: will not over-write existing file "'strings.c'"
  2401. else
  2402. sed 's/^X//' >strings.c <<'@//E*O*F strings.c//'
  2403. X/*
  2404. X** vn news reader.
  2405. X**
  2406. X** strings.c - character strings
  2407. X**
  2408. X** see copyright disclaimer / history in vn.c source file
  2409. X*/
  2410. X
  2411. X#include "vn.h"
  2412. X#include "head.h"
  2413. X
  2414. Xchar *Version = "12/86";
  2415. X
  2416. Xchar *No_msg = "No articles";
  2417. Xchar *Hdon_msg = "Headers being printed";
  2418. Xchar *Hdoff_msg = "Headers being suppressed";
  2419. Xchar *Roton_msg = "ROT 13";
  2420. Xchar *Rotoff_msg = "NO ROT";
  2421. X
  2422. Xchar *Aformat = AFORMAT;
  2423. X
  2424. Xchar *Contstr = "  ******** any key to continue ********";
  2425. X
  2426. Xchar *R_head = RHEAD;
  2427. Xchar *M_head = MHEAD;
  2428. Xchar *P_head = PHEAD;
  2429. Xchar *D_head = DHEAD;
  2430. Xchar *F_head = FHEAD;
  2431. Xchar *FT_head = FTHEAD;
  2432. Xchar *T_head = THEAD;
  2433. Xchar *L_head = LHEAD;
  2434. Xchar *N_head = NHEAD;
  2435. Xchar *RT_head = RTHEAD;
  2436. Xchar *TO_head = TOHEAD;
  2437. Xchar *DIS_head = DISHEAD;
  2438. @//E*O*F strings.c//
  2439. if test 720 -ne "`wc -c <'strings.c'`"; then
  2440.     echo shar: error transmitting "'strings.c'" '(should have been 720 characters)'
  2441. fi
  2442. fi # end of overwriting check
  2443. echo shar: extracting "'tmpnam.c'" '(420 characters)'
  2444. if test -f 'tmpnam.c' ; then 
  2445.   echo shar: will not over-write existing file "'tmpnam.c'"
  2446. else
  2447. sed 's/^X//' >tmpnam.c <<'@//E*O*F tmpnam.c//'
  2448. X/*
  2449. X** vn news reader.
  2450. X**
  2451. X** tmpnam.c - tmpnam() replacement for UCB, also uses non-generic name.
  2452. X**
  2453. X** see copyright disclaimer / history in vn.c source file
  2454. X*/
  2455. X
  2456. X#include <stdio.h>
  2457. X#include "config.h"
  2458. X
  2459. Xchar *tmpnam (buf)
  2460. Xchar *buf;
  2461. X{
  2462. X    static char *ptr = VNTEMPNAME;
  2463. X
  2464. X    /* depends on string initialized above */
  2465. X    sprintf (ptr+TMP_XOFFSET,"XXXXXX");
  2466. X
  2467. X    mktemp (ptr);
  2468. X
  2469. X    if (buf != NULL)
  2470. X        strcpy (buf,ptr);
  2471. X
  2472. X    return (ptr);
  2473. X}
  2474. @//E*O*F tmpnam.c//
  2475. if test 420 -ne "`wc -c <'tmpnam.c'`"; then
  2476.     echo shar: error transmitting "'tmpnam.c'" '(should have been 420 characters)'
  2477. fi
  2478. fi # end of overwriting check
  2479. echo shar: "End of archive 1 (of 3)."
  2480. cp /dev/null ark1isdone
  2481. DONE=true
  2482. for I in 1 2 3; do
  2483.     if test -! f ark${I}isdone; then
  2484.         echo "You still need to run archive ${I}."
  2485.         DONE=false
  2486.     fi
  2487. done
  2488. case $DONE in
  2489.     true)
  2490.         echo "You have run all 3 archives."
  2491.         echo 'Now read the README'
  2492.         ;;
  2493. esac
  2494. ##  End of shell archive.
  2495. exit 0
  2496.